package jsen.tool.ddd.demo.domain.parking;

import jsen.tool.ddd.adapter.event.IEventBus;
import jsen.tool.ddd.adapter.infrastructure.specification.ISpecification;
import jsen.tool.ddd.demo.domain.base.DomainObject;
import jsen.tool.ddd.demo.domain.parking.event.ParkingStatusChange;
import jsen.tool.ddd.demo.domain.parking.factory.ParkingRecordFactory;
import jsen.tool.ddd.demo.domain.spec.NoSpec;
import jsen.tool.ddd.domain.AggregateObject;
import lombok.Builder;
import lombok.Getter;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 监控，检查剩余车位
 *
 * @author jsen
 * @date 2021/10/6
 */
@AggregateObject(name = "Location", desc = "车位，职责负责车位状态维护")
@Getter
@Builder
public class ParkingLotMonitor implements DomainObject {
    private final ISpecification<DomainObject> strict = new NoSpec<>();
    private final List<Parking> parkingList = new ArrayList<>();
    private final Set<Car> carList = new HashSet<>();
    private final List<ParkingRecord> parkingRecordList = new ArrayList<>();

    public void startMonitor(IEventBus bus) {
        new Thread(() -> {
            while (true) {
                int free = 0;
                int busy = 0;
                for (Parking parking : parkingList) {
                    if (parking.hasCar(carList)) {
                        busy++;
                    } else {
                        free++;
                    }
                }

                bus.fireEvent(ParkingStatusChange.builder().freeLocationCnt(free).busyLocationCnt(busy).build());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }).start();

    }

    public boolean carIn(Car car) {
        parkingRecordList.add(ParkingRecordFactory.build(car));
        return carList.add(car);
    }

    public boolean carOut(Car car) {
        parkingRecordList.stream().filter(i -> car.getPlate().equals(i.getCar().getPlate()))
                .forEach(ParkingRecord::carOut);
        return carList.remove(car);
    }


}
